<template>
  <div style="padding: 20px">
    <Alert message="上传示例" type="info" show-icon>
      <template #icon><smile-outlined /></template>
    </Alert>
    <div class="demoTittle">单文件上传</div>
    <div class="demoTittle2">使用a-upload组件，配置action，headers等属性</div>
    <a-form :label-col="labelCol" :wrapper-col="wrapperCol">
      <a-form-item label="课程附件" :rules="[{ required: true, message: '请上传文件' }]">
        <div style="display: flex; align-items: center">
          <a-upload
            v-model:file-list="fileList"
            name="file"
            :action="`${actionUrl}/manage/upload/uploadFile/5`"
            :headers="uploadHeader"
            :max-count="9"
          >
            <div>
              <a-button type="primary" ghost> 点击上传 </a-button>
            </div>

            <template #itemRender="{ file, actions }"
              ><div class="uploadList">
                <a-space>
                  <span :style="file.status === 'error' ? 'color: red' : ''">{{ file.name }}</span>
                  <a href="javascript:;" @click="actions.remove">删除</a>
                </a-space>
              </div>
            </template>
          </a-upload>
          <span style="color: rgba(153, 153, 153, 1); margin-left: 8px"
            >格式要求：请上传文档或视频格式（不可上传.wps格式）,最多上传9个</span
          >
        </div>
      </a-form-item>
    </a-form>
    <div class="demoTittle" style="margin-top: 50px">多文件上传</div>
    <div class="demoTittle2">multiple开启后按住 ctrl 可选择多个文件。</div>
    <a-form :label-col="labelCol" :wrapper-col="wrapperCol">
      <a-form-item label="课程附件" :rules="[{ required: true, message: '请上传文件' }]">
        <div style="display: flex; align-items: center">
          <a-upload
            v-model:file-list="fileList2"
            name="file"
            :action="`${actionUrl}/manage/upload/uploadFile/5`"
            :headers="uploadHeader"
            :multiple="true"
          >
            <div>
              <a-button type="primary"> 点击上传 </a-button>
            </div>

            <template #itemRender="{ file, actions }"
              ><div class="uploadList">
                <a-space>
                  <span :style="file.status === 'error' ? 'color: red' : ''">{{ file.name }}</span>
                  <a href="javascript:;" @click="actions.remove">删除</a>
                </a-space>
              </div>
            </template>
          </a-upload>
          <span style="color: rgba(153, 153, 153, 1); margin-left: 8px"
            >只能上传 txt,pdf,gif,jpeg,png,rar,zip,doc,docx,xls,xlsx,ppt,pptx
            类型的附件，且耽搁附件须小于10M，大附件请拆分上传</span
          >
        </div>
      </a-form-item>
    </a-form>
    <div class="demoTittle" style="margin-top: 50px">上传进度</div>
    <div class="demoTittle2">自定义progress进度条，属性list-type设置为picture</div>
    <div style="width: 50%">
      <a-upload-dragger
        v-model:fileList="fileList3"
        name="file"
        :multiple="true"
        list-type="picture"
        :action="`${actionUrl}/manage/upload/uploadFile/5`"
        :headers="uploadHeader"
        :progress="progress"
        @change="handleChange"
      >
        <p class="ant-upload-drag-icon">
          <inbox-outlined></inbox-outlined>
        </p>
        <p class="ant-upload-text">将电脑里的文件拖拽到这里上传</p>
        <p class="ant-upload-hint"> </p>
      </a-upload-dragger>
    </div>
    <div class="demoTittle" style="margin-top: 50px">图片上传</div>
    <div class="demoTittle2">使用照片墙，list-type="picture-card"</div>
    <div class="clearfix">
      <div class="demoTittle2">- 一般用于普通图片上传</div>
      <a-upload
        v-model:file-list="fileList4"
        :action="`${actionUrl}/manage/upload/uploadFile/5`"
        :headers="uploadHeader"
        list-type="picture-card"
        @preview="handlePreview"
      >
        <div v-if="fileList.length < 8">
          <plus-outlined color="#0052D9" style="font-size: 24px" />
        </div>
      </a-upload>
      <a-modal
        :open="previewVisible"
        :title="previewTitle"
        :footer="null"
        @cancel="handleImgCancel"
      >
        <img alt="example" style="width: 100%" :src="previewImage" />
      </a-modal>
    </div>
    <div class="clearfix">
      <div class="demoTittle2">- 图片视频混合上传，视频插件使用vue3-video-play</div>
      <a-upload
        name="file"
        v-model:file-list="fileList5"
        :action="`${actionUrl}/manage/upload/uploadFile/5`"
        :headers="uploadHeader"
        list-type="picture-card"
        @preview="handlePreview"
        @change="handleChange2"
      >
        <div v-if="fileList.length < 9">
          <plus-outlined color="#0052D9" style="font-size: 24px" />
        </div>
      </a-upload>
      <a-modal
        v-if="fileType == 'image/jpeg' || fileType == 'image/png'"
        :title="previewTitle"
        :open="previewVisible"
        width="800px"
        :footer="null"
        @cancel="handleImgCancel"
      >
        <img alt="example" style="width: 100%" :src="previewImage" />
      </a-modal>
      <a-modal
        v-if="fileType == 'video/mp4'"
        width="800px"
        :title="previewTitle"
        :open="previewVisible"
        :footer="null"
        @cancel="handleVideoCancel"
      >
        <videoPlay id="video" width="100%" :src="previewVideo" />
      </a-modal>
    </div>
    <div class="clearfix">
      <div class="demoTittle2">- 特殊尺寸图片上传</div>
      <a-upload
        v-model:file-list="fileList6"
        name="avatar"
        list-type="picture-card"
        class="avatar-uploader"
        :show-upload-list="false"
        :action="`${actionUrl}/manage/upload/uploadFile/5`"
        :headers="uploadHeader"
        :before-upload="beforeUpload"
        @change="handleChange3"
      >
        <div class="imagess" v-if="imageUrl" @mouseenter="imageEnter" @mouseleave="imageLeave">
          <img :src="imageUrl" alt="图片" :width="343" :height="192" />
          <div v-if="boxStatus == true" class="imgBox">
            <div class="imgBox-btn">重新上传</div>
          </div>
        </div>

        <div v-else>
          <loading-outlined v-if="loading"></loading-outlined>
          <plus-outlined color="#0F53AC" style="font-size: 24px" />
          <div class="ant-upload-button">上传封面</div>
        </div>
      </a-upload>
    </div>
  </div>
</template>
<script setup lang="ts">
  import { ref } from 'vue';
  import { Storage } from '@/utils/Storage';
  import 'vue3-video-play/dist/style.css';
  import { videoPlay } from 'vue3-video-play';
  import { Alert, message } from 'ant-design-vue';
  import { ACCESS_TOKEN_KEY } from '@/enums/cacheEnum';
  import type { UploadChangeParam, UploadProps } from 'ant-design-vue';
  import {
    SmileOutlined,
    InboxOutlined,
    PlusOutlined,
    LoadingOutlined,
  } from '@ant-design/icons-vue';

  const fileList = ref([]);
  const fileList2 = ref([]);
  const fileList3 = ref([]);
  const fileList4 = ref([]);
  const fileList5 = ref([]);
  const fileList6 = ref([]);
  const loading = ref<boolean>(false);
  const imageUrl = ref<string>('');

  const labelCol = {
    style: { width: '82px' },
  };
  const wrapperCol = {
    span: 16,
  };

  //上传
  const actionUrl = ref(import.meta.env.VITE_BASE_API);
  const uploadHeader = {
    'API-User-Token': Storage.get(ACCESS_TOKEN_KEY),
  };

  const progress: UploadProps['progress'] = {
    strokeColor: {
      '0%': '#108ee9',
      '100%': '#1677FF',
    },
    size: 6,
    strokeWidth: 3,
    format: (percent: number) => `${parseFloat(percent.toFixed(2))}%`,
    class: 'test',
  };

  //墙
  const previewTitle = ref('');
  const previewVisible = ref(false);
  const previewList = ref([] as any);
  const previewImage = ref('' as any);
  const previewVideo = ref('' as any);
  const fileType = ref('' as any);

  const handleImgCancel = () => {
    previewVisible.value = false;
    previewTitle.value = '';
  };
  const handleVideoCancel = () => {
    previewVisible.value = false;
    let myVideo = document.getElementsByTagName('video');
    let arr = Array.from(myVideo);
    arr.forEach((item) => {
      //关闭时暂停播放
      item.pause();
    });
  };

  const handlePreview = async (file: any) => {
    if (!file.url && !file.preview) {
      file.preview = (await getBase64(file.originFileObj)) as string;
    }
    fileType.value = file.type;
    if (file.type == 'image/jpeg' || file.type == 'image/png') {
      previewImage.value = file.url || file.preview;
    } else if (file.type == 'video/mp4') {
      previewVideo.value = file.url || file.preview;
    }
    previewVisible.value = true;
    previewTitle.value = file.name || file.url.substring(file.url.lastIndexOf('/') + 1);
  };

  function getBase64(file: File) {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.readAsDataURL(file);
      reader.onload = () => resolve(reader.result);
      reader.onerror = (error) => reject(error);
    });
  }

  const getVideoBase64 = (url) => {
    return new Promise(function (resolve, reject) {
      let dataURL = '';
      let video = document.createElement('video');
      video.setAttribute('crossOrigin', 'anonymous'); //处理跨域
      video.setAttribute('src', url);
      video.setAttribute('width', '100');
      video.setAttribute('height', '100');
      video.setAttribute('preload', 'auto');
      video.addEventListener('loadeddata', function () {
        let canvas = document.createElement('canvas'),
          width = video.width, //canvas的尺寸和图片一样
          height = video.height;
        canvas.width = width;
        canvas.height = height;
        canvas.getContext('2d')?.drawImage(video, 0, 0, width, height); //绘制canvas
        dataURL = canvas.toDataURL('image/jpeg'); //转换为base64
        resolve(dataURL);
      });
    });
  };

  function getBase64s(img: Blob, callback: (base64Url: string) => void) {
    const reader = new FileReader();
    reader.addEventListener('load', () => callback(reader.result as string));
    reader.readAsDataURL(img);
  }

  const handleChange = (info: UploadChangeParam) => {
    if (info.file.status !== 'uploading') {
      console.log(info.file, info.fileList);
    }
    if (info.file.status === 'done') {
      message.success(`${info.file.name} 文件上传成功！`);
    } else if (info.file.status === 'error') {
      message.error(`${info.file.name} 文件上传失败。`);
    }
  };

  const handleChange2 = ({ file, fileList, event }: UploadChangeParam) => {
    previewList.value = fileList;

    previewList.value.map(async (item) => {
      let url = item?.response?.data.fileIds[0];

      if (item.type == 'video/mp4' && url) {
        let video64 = await getVideoBase64(url);
        item.thumbUrl = video64;
      }
    });
  };

  const handleChange3 = (info: UploadChangeParam) => {
    if (info.file.status === 'uploading') {
      loading.value = true;
      return;
    }
    if (info.file.status === 'done') {
      getBase64s(info.file.originFileObj as any, (base64Url: string) => {
        imageUrl.value = base64Url;
        loading.value = false;
      });
    }
    if (info.file.status === 'error') {
      loading.value = false;
      message.error('上传失败');
    }
  };
  const beforeUpload = (file) => {
    const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
    if (!isJpgOrPng) {
      message.error('你仅可以上传jpeg格式或者png格式的图片!');
    }
    const isLt2M = file.size / 1024 / 1024 < 2;
    if (!isLt2M) {
      message.error('图片必须小于2MB!');
    }
    return isJpgOrPng && isLt2M;
  };

  const boxStatus = ref<Boolean>(false);

  //鼠标移入
  const imageEnter = () => {
    boxStatus.value = true;
  };

  //鼠标移出
  const imageLeave = () => {
    boxStatus.value = false;
  };
</script>
<style lang="less" scoped>
  .demoTittle {
    font-size: 20px;
    font-weight: 400;
    color: #444444;
    margin: 20px 0;
  }
  .demoTittle2 {
    font-size: 14px;
    color: #494a4a;
    margin-bottom: 18px;
  }
  :deep(.ant-upload-wrapper .ant-upload-list:has(.uploadList)) {
    display: flex;
    margin-top: 12px;
  }
  .uploadList {
    margin-right: 24px;
  }
  :deep(
      .ant-upload-wrapper
        .ant-upload-list.ant-upload-list-picture
        .ant-upload-list-item
        .ant-upload-list-item-progress
    ) {
    bottom: 8px;
  }
  :deep(.ant-upload-list .ant-upload-list-item-container .ant-upload-list-item:hover) {
    background-color: #f2f6fc;
  }
  :deep(.ant-upload-wrapper .ant-upload-list.ant-upload-list-picture-card .ant-upload-list-item) {
    padding: 0;
  }
  :deep(
      .ant-upload-wrapper
        .ant-upload-list.ant-upload-list-picture-card
        .ant-upload-list-item::before
    ) {
    padding: 0 8px;
    width: 100%;
    height: 100%;
  }

  //上传进度条
  :deep(
      .ant-upload-wrapper.ant-upload-picture-card-wrapper
        .ant-upload-list.ant-upload-list-picture-card
        .ant-upload-list-item-progress
    ) {
    width: 100%;
    padding: 0 8px;
  }

  :deep(
      .avatar-uploader.ant-upload-wrapper.ant-upload-picture-card-wrapper
        .ant-upload.ant-upload-select
    ) {
    width: 343px;
    height: 192px;
    img {
      border-radius: 4px;
    }
  }

  .ant-upload-select-picture-card i {
    font-size: 32px;
    color: #999;
  }

  .ant-upload-select-picture-card .ant-upload-button {
    margin-top: 8px;
    color: #0052d9;
    padding: 3px 8px;
    border-radius: 4px;
    background: #ffffff;
    border: 1px solid #f0f0f0;
  }

  .imagess {
    position: relative;
    width: 100%;
    height: 100%;
  }

  .imagess img {
    position: absolute;
    top: 0;
    left: 0;
  }

  .imgBox {
    width: 343px;
    height: 192px;
    background-color: #00000033;
    position: absolute;
    z-index: 9;
    display: flex;
    align-items: center;
    justify-content: center;

    &-btn {
      border-radius: 4px;
      color: #ffffff;
      padding: 3px 8px;
      background-color: rgba(0, 0, 0, 0.8);
    }
  }
</style>
